/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.frontendproject;

import com.inspur.edp.ide.setting.api.entity.Deployment;
import com.inspur.edp.lcm.debugger.api.service.DebuggerService;
import com.inspur.edp.lcm.metadata.api.entity.ExtractContext;
import com.inspur.edp.lcm.metadata.api.entity.GspProject;
import com.inspur.edp.lcm.metadata.api.service.PackageGenerateService;
import com.inspur.edp.lcm.metadata.api.service.ProjectExtendService;
import com.inspur.edp.web.common.constant.FrontendProjectConstant;
import com.inspur.edp.web.common.entity.TerminalType;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.logger.WebLogger;
import com.inspur.edp.web.common.metadata.GspProjectUtility;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.frontendproject.webservice.FormDynamicParameter;
import com.inspur.edp.web.jitengine.dynamicform.DynamicFormMetaFileNameGenerator;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;


/**
 * 前端工程部署器： 将生成的前端文件部署到指定SU下
 *
 * @author guozhiqi
 */
public class FrontendProjectDeployer {
    /**
     * 前端生成物部署
     *
     * @param projectPath 工程路径
     */
    public final void deploy(String projectPath) {
        if (StringUtility.isNullOrEmpty(projectPath)) {
            return;
        }
        String projectName = GspProjectUtility.getProjectName(projectPath);
        // 部署PC
        deploy(projectPath, projectName, TerminalType.PC, false);
        //部署mobile
        deploy(projectPath, projectName, TerminalType.MOBILE, false);

        // 部署前端交付物至目标publish目录
        deployToPublish(projectPath);
    }

    /**
     * 前端生成物部署
     *
     * @param projectPath 工程路径
     */
    public final void deployForJieXi(String projectPath, FormDynamicParameter jieXiParameter) {
        if (StringUtility.isNullOrEmpty(projectPath)) {
            return;
        }
        String projectName = GspProjectUtility.getProjectName(projectPath);
        boolean isUseSingleForm = jieXiParameter != null && jieXiParameter.isUseSingleForm();

        // 部署前端交付物至目标publish目录
        if (!isUseSingleForm) {
            // 部署PC
            deploy(projectPath, projectName, TerminalType.PC, isUseSingleForm);
            //部署mobile
            //deploy(projectPath, projectName, TerminalType.MOBILE, isJieXiForm);
            deployToPublish(projectPath);
        } else {
            // 仅拷贝metadata.js 及其对应的service编译后的脚本
            String targetDeployBasePath = getTargetDeployBasePath(projectPath, TerminalType.PC);
            String strFormPath = FileUtility.combine(projectPath, "src", FrontendProjectConstant.PROJECT_GENERATE_PATH_FOR_Dynamic);
            strFormPath = FileUtility.combine(strFormPath, "dynamicform", jieXiParameter.getFormCode().toLowerCase());


            String targetFormMetadataPath = FileUtility.combineOptional(targetDeployBasePath, "web", projectName.toLowerCase(), jieXiParameter.getFormCode().toLowerCase());

            if (FileUtility.exists(strFormPath)) {
                // 进行文件拷贝
                // 拷贝对应的expression 和 i18n 文件夹
                String dynamicFormExpressionFolder = FileUtility.combine(strFormPath, "expressions");
                String targetFormExpressionFolder = FileUtility.combine(targetFormMetadataPath, "expressions");

                String dynamicFormI18nFolder = FileUtility.combine(strFormPath, "i18n");
                String targetDynamicFormI18nFolder = FileUtility.combine(targetFormMetadataPath, "i18n");

                String dynamicFormHtmlTemplateFolder = FileUtility.combine(strFormPath, "htmltemplate");
                String targetDynamicFormHtmlTemplateFolder = FileUtility.combine(targetFormMetadataPath, "htmltemplate");

                if (FileUtility.exists(dynamicFormExpressionFolder)) {
                    FileUtility.copyFolder(dynamicFormExpressionFolder, targetFormExpressionFolder);
                }
                if (FileUtility.exists(dynamicFormI18nFolder)) {
                    FileUtility.copyFolder(dynamicFormI18nFolder, targetDynamicFormI18nFolder);
                }

                if (FileUtility.exists(dynamicFormHtmlTemplateFolder)) {
                    FileUtility.copyFolder(dynamicFormHtmlTemplateFolder, targetDynamicFormHtmlTemplateFolder);
                }
            }

            // 执行metadata.js 文件拷贝
//            String dynamicFormMetadataJsFilenmae = DynamicFormMetaFileNameGenerator.generateMetaFileName(jieXiParameter.getFormCode());
//            String dynamicFormMetadataJs = FileUtility.combine(strFormPath, dynamicFormMetadataJsFilenmae);
//            String targetMetadataJsFilePath = FileUtility.combine(targetFormMetadataPath, dynamicFormMetadataJsFilenmae);
//            FileUtility.copyFile(dynamicFormMetadataJs, targetMetadataJsFilePath, true);

            //复制
            String strFormServicePath = FileUtility.combineOptional(projectPath, "src", FrontendProjectConstant.PROJECT_GENERATE_PATH_FOR_Dynamic, "services", jieXiParameter.getFormCode().toLowerCase());
            String customServicePath = FileUtility.combine(strFormServicePath, "services", "dist-rollup");
            if (FileUtility.exists(customServicePath)) {
                String targetFormMetadataServicePath = FileUtility.combine(targetFormMetadataPath, "dynamicjs");
                // 删除目标文件目录
                FileUtility.deleteFolder(targetFormMetadataServicePath);
                FileUtility.copyFolder(customServicePath, targetFormMetadataServicePath);
            }

            // 部署前端元数据
            DeployFrontMetadata(projectPath);
        }
    }

    /**
     * 生成物部署
     *
     * @param projectPath  工程路径
     * @param projectName  工程名称
     * @param terminalType 表单类型，分类PC和移动表单
     */
    private void deploy(String projectPath, String projectName, TerminalType terminalType, boolean isSingleDynamicForm) {
        this.deployInfo(projectPath, projectName, terminalType, false);
    }

    private void deployInfo(String projectPath, String projectName, TerminalType terminalType, boolean isJieXiForm) {
        String sourceProjectProductPath = FrontendProjectUtility.getProjectSourceCodeBuildPath(projectPath, projectName, terminalType, isJieXiForm);
        if (FileUtility.exists(sourceProjectProductPath)) {
            // 获取待部署的目标路径
            String targetDeployBasePath = getTargetDeployBasePath(projectPath, terminalType);

            // 将待部署文件拷贝到服务端部署目录
            deployFrontendProjectProduct(projectName, sourceProjectProductPath, targetDeployBasePath, terminalType);

            copyI18nResource(projectPath, targetDeployBasePath, projectName, terminalType, false);
        }
    }

    /**
     * 部署前端交付物至publish目录
     *
     * @param projectPath
     */
    private void deployToPublish(String projectPath) {
        try {
            GspProject projectInfo = GspProjectUtility.getProjectInformation(projectPath);
            String projectName = projectInfo.getMetadataProjectName();
            // 移除工程名后的路径
            projectPath = projectPath.substring(0, projectPath.toLowerCase().lastIndexOf(projectName.toLowerCase()) + projectName.length());

            ExtractContext extractContext = new ExtractContext();
            extractContext.setProjectPath(projectPath);
            extractContext.setDeployPath(projectInfo.getSuDeploymentPath());
            FrontendProjectExtractor projectExtractor = new FrontendProjectExtractor();
            projectExtractor.extract(extractContext);
        } catch (Exception ex) {
            WebLogger.Instance.info("部署前端脚本至publish目录失败" + ex, this.getClass().getName());
        }
    }

    private String getTargetDeployBasePath(String projectPath, TerminalType terminalType) {
        String targetDeployBasePath = "";

        // 获取默认的部署环境信息
        DebuggerService debuggerService = SpringBeanUtils.getBean(DebuggerService.class);
        Deployment defaultDebuggerDeployment = debuggerService.getDefaultDebugServerStatus();
        GspProject projectInfo = GspProjectUtility.getProjectInformation(projectPath);

        String serverDeployPath = getDeployServerPath(defaultDebuggerDeployment);

        targetDeployBasePath = FileUtility.combine(serverDeployPath, "web", projectInfo.getSuDeploymentPath());

        return targetDeployBasePath;
    }

    /**
     * 获取部署位置
     *
     * @param defaultDebuggerDeployment
     * @return
     */
    private String getDeployServerPath(Deployment defaultDebuggerDeployment) {
        String serverRootPath = "";
        if (defaultDebuggerDeployment == null ||
                "localhost".equalsIgnoreCase(defaultDebuggerDeployment.getName()) ||
                "current server".equalsIgnoreCase(defaultDebuggerDeployment.getName())) {
            // 获取服务器端部署目录
            serverRootPath = FileUtility.getCurrentWorkPath(false);

        } else {
            if (StringUtility.isNullOrEmpty(defaultDebuggerDeployment.getServerPath())) {
                throw new RuntimeException("默认环境未设置路径");
            }
            WebLogger.Instance.debug("use default debugger deploy,the path is " + defaultDebuggerDeployment.getServerPath(), FrontendProjectDeployer.class.getName());
            serverRootPath = defaultDebuggerDeployment.getServerPath();
        }
        return serverRootPath;
    }

    public final void deployForBabel(String projectPath) {
        if (StringUtility.isNullOrEmpty(projectPath)) {
            return;
        }

        String projectName = GspProjectUtility.getProjectName(projectPath);
        String ProductPathForBabel = FileUtility.combine(FrontendProjectConstant.FRONTEND_PROJECT_COMPILE_PATH, FrontendProjectConstant.PROJECT_GENERATE_PATH_FOR_BABEL, FrontendProjectConstant.PROJECT_BUILD_PATH);
        String sourcePath = FileUtility.combine(projectPath, ProductPathForBabel, projectName + "forbabel");
        boolean isSourcePathExists = FileUtility.exists(sourcePath);
        if (!isSourcePathExists) {
            return;
        }

        String targetBaseDeployPath = "";
        // 获取默认的部署环境信息
        DebuggerService debuggerService = SpringBeanUtils.getBean(DebuggerService.class);
        Deployment defaultDebuggerDeployment = debuggerService.getDefaultDebugServerStatus();
        GspProject projectInfo = GspProjectUtility.getProjectInformation(projectPath);

        String deployServerPath = this.getDeployServerPath(defaultDebuggerDeployment);
        targetBaseDeployPath = FileUtility.combine(deployServerPath, "web", projectInfo.getSuDeploymentPath());

        // 将待部署文件拷贝到服务端部署目录
        DeployFrontendProjectProductsForBabel(projectName, sourcePath, targetBaseDeployPath);

        copyI18nResource(projectPath, targetBaseDeployPath, projectName, TerminalType.PC, true);

        // 调用元数据的部署，把元数据也部署过去。
        long beforeDT = System.currentTimeMillis();
        DeployFrontMetadata(projectPath);
        long afterDt = System.currentTimeMillis();
        long ts = afterDt - beforeDT;
        WebLogger.Instance.info("部署前端元数据所需的时间为" + ts + "ms", FrontendProjectDeployer.class.getName());
    }

    /**
     * 复制i18n资源文件
     *
     * @param projectPath
     * @param targetPath
     * @param projectName
     * @param terminalType
     * @param isBabel
     */
    private void copyI18nResource(String projectPath, String targetPath, String projectName, TerminalType terminalType, boolean isBabel) {
        String i18nResourceRelavtivePath = terminalType.getWebDevI18nRelativePath();
        String sourceI18nResourcePath = java.nio.file.Paths.get(projectPath).resolve(i18nResourceRelavtivePath).toString();

        String formPublishPath = terminalType.getPublishPathName();
        String targetI18nResourcePath = FileUtility.combine(targetPath, formPublishPath, projectName);
        if (isBabel) {
            targetI18nResourcePath = FileUtility.combine(targetPath, formPublishPath, projectName + "forbabel");
        }

        if ((new java.io.File(sourceI18nResourcePath)).isDirectory()) {
            FileUtility.copyFolder(sourceI18nResourcePath, targetI18nResourcePath);
        }
    }

    /**
     * 拷贝前端工程生成物到服务端部署目录
     */
    private void deployFrontendProjectProduct(String projectName, String sourcePath, String destinationBasePath, TerminalType terminalType) {
        if (StringUtility.isNullOrEmpty(projectName) || StringUtility.isNullOrEmpty(sourcePath) || StringUtility.isNullOrEmpty(destinationBasePath)) {
            return;
        }

        String formPublishPath = terminalType.getPublishPathName();
        String destinationPath = FileUtility.combine(destinationBasePath, formPublishPath, projectName);

        copyProducts(sourcePath, destinationPath);
    }

    /**
     * 拷贝前端工程生成物到服务端部署目录，使用babel快速编译时使用
     */
    private void DeployFrontendProjectProductsForBabel(String projectName, String sourcePath, String destinationBasePath) {
        if (StringUtility.isNullOrEmpty(projectName) || StringUtility.isNullOrEmpty(sourcePath) || StringUtility.isNullOrEmpty(destinationBasePath)) {
            return;
        }
        String destinationPath = FileUtility.combine(destinationBasePath, TerminalType.PC.getPublishPathName(), projectName + "forbabel");

        copyProducts(sourcePath, destinationPath);
    }

    /**
     * 拷贝生成物到指定目录
     */
    private void copyProducts(String sourcePath, String destinationPath) {
        if (StringUtility.isNullOrEmpty(sourcePath) || StringUtility.isNullOrEmpty(destinationPath)) {
            return;
        }

        FileUtility.copyFolder(sourcePath, destinationPath);
    }

    private void DeployFrontMetadata(String projectPath) {

        PackageGenerateService packageGenerateService = SpringBeanUtils.getBean(PackageGenerateService.class);
        packageGenerateService.generatePackage(projectPath);

        ProjectExtendService projectExtendService = SpringBeanUtils.getBean(ProjectExtendService.class);
        ExtractContext extractContext = new ExtractContext();
        extractContext.setProjectPath(projectPath);

        projectExtendService.extract(projectPath);

        projectExtendService.migration(projectPath);
    }
}
